﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ZOIL.Framework.Core;
using ZOIL.Framework.Presentation;
using System.Windows.Controls.Primitives;

namespace ZOIL.Library.Components
{
    /// <summary>
    ///     A column that displays all metadata (& of arbitrary type) which can be chosen via a combobox in the header.
    /// </summary>
    public class VHyperGrid2UACColumn : VHyperGrid2TemplateColumn
    {
        #region Constructors
        ComboBox attributeSelectionCB = new ComboBox();

        public VHyperGrid2UACColumn()
        {
            #region create ComboBox for attribute selection
            attributeSelectionCB.Margin = new Thickness(0, 1, 0, 0);
            attributeSelectionCB.IsEditable = false;
            attributeSelectionCB.SelectionChanged += new SelectionChangedEventHandler(attributeSelectionCB_SelectionChanged);
            attributeSelectionCB.Loaded += new RoutedEventHandler(attributeSelectionCB_Loaded);
            #endregion

            //add combobox as header
            this.Header = attributeSelectionCB;
        }

        void attributeSelectionCB_Loaded(object sender, RoutedEventArgs e)
        {
            attributeSelectionCB.ItemsSource = getSortedAttributesWithType();
            attributeSelectionCB.DisplayMemberPath = "Name";            
            attributeSelectionCB.SelectedIndex = 0;

            // dirty hack beacause datagrid-header is not loaded when combobox is...
            attributeSelectionCB_SelectionChanged(sender, null);
        }

        void attributeSelectionCB_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //TODO reset sorting-arrow if selection is changed...
            ComboBox attributeSelectionCB = (ComboBox)sender;
            if (attributeSelectionCB.IsVisible)
            {
                String currentCBItemText = ((PropertyInfo)attributeSelectionCB.SelectedValue).Name;
                DataGridColumnHeader UAC_columnHeader = ZTreeHelper.TryFindParent<DataGridColumnHeader>(attributeSelectionCB);
                DataGrid myDG = ZTreeHelper.TryFindParent<DataGrid>(UAC_columnHeader);

                //get attribute-names for combobox
                this.SortMemberPath = currentCBItemText;

                //reset sort-arrow of UAC when selection is changed
                UAC_columnHeader.Column.SortDirection = null;

                //set template for selected attribute and bind it to the column
                DataTemplate newDT = new DataTemplate();

                FrameworkElementFactory templatedElement = new FrameworkElementFactory();

                Binding newBinding = new Binding();
                newBinding.Path = new PropertyPath(currentCBItemText);

                Type currentAttributeType = ((PropertyInfo)attributeSelectionCB.SelectedValue).PropertyType;
                if (currentAttributeType == typeof(IList<String>))
                {
                    newBinding.Converter = new StringConcatenator();
                    templatedElement = new FrameworkElementFactory(typeof(TextBlock));
                    templatedElement.SetBinding(TextBlock.TextProperty, newBinding);
                }
                else if (currentAttributeType == typeof(String))
                {
                    templatedElement = new FrameworkElementFactory(typeof(TextBlock));
                    templatedElement.SetBinding(TextBlock.TextProperty, newBinding);
                }
                else if (currentAttributeType == typeof(DateTime?))
                {
                    String propPath = newBinding.Path.Path + ".Year";
                    newBinding.Path = new PropertyPath(propPath);
                    templatedElement = new FrameworkElementFactory(typeof(TextBlock));
                    templatedElement.SetBinding(TextBlock.TextProperty, newBinding);
                }
                else if (currentAttributeType == typeof(Uri))
                {
                    if (currentCBItemText.Equals("PosterPath"))
                    {
                        templatedElement = new FrameworkElementFactory(typeof(Image));
                        templatedElement.SetBinding(Image.SourceProperty, newBinding);
                    }
                    else if (currentCBItemText.Equals("SmallUrl"))
                    {
                        templatedElement = new FrameworkElementFactory(typeof(Image));
                        templatedElement.SetBinding(Image.SourceProperty, newBinding);
                    }
                    else if (currentCBItemText.Equals("BuddyIconURL"))
                    {
                        templatedElement = new FrameworkElementFactory(typeof(Image));
                        templatedElement.SetBinding(Image.SourceProperty, newBinding);
                    }
                    else if (currentCBItemText.Equals("MoviePath"))
                    {
                        templatedElement = new FrameworkElementFactory(typeof(VMoviePlayer));
                        templatedElement.SetBinding(VMoviePlayer.movieLinkProperty, newBinding);

                        //set movietitle
                        Binding titleBinding = new Binding();
                        titleBinding.Path = new PropertyPath("Title");
                        templatedElement.SetBinding(VMoviePlayer.movieTitleProperty, titleBinding);
                    }
                    else
                    {
                        templatedElement = new FrameworkElementFactory(typeof(TextBlock));
                        templatedElement.SetBinding(TextBlock.TextProperty, newBinding);
                    }
                }
                else
                {
                    templatedElement = new FrameworkElementFactory(typeof(TextBlock));
                    templatedElement.SetBinding(TextBlock.TextProperty, newBinding);
                }

                //set trimming & wrapping for textual values
                if (templatedElement.Type == typeof(TextBlock))
                {
                    templatedElement.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis);
                    templatedElement.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap);
                }
                else
                {
                    templatedElement.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Top);
                }

                //TODO alignment of attributes (numerical-values align right, textual align left, image & movies align center, ...)
                //TODO cut or fill to correct length (numerical attributes sometimes dont have the same amount of numbers after decimal-point)

                newDT.VisualTree = templatedElement;
                this.CellTemplate = newDT;
            }
        }
        #endregion

        #region Attribute Helpers
        private HashSet<PropertyInfo> getSortedAttributesWithType()
        {
            HashSet<PropertyInfo> atts = new HashSet<PropertyInfo>();

            //just get the attributes without the type (you can get the type of the parent of the attribute via currAtt.ReflectedType)
            foreach (KeyValuePair<Type, HashSet<PropertyInfo>> currType in ((VHyperGrid2c)this.DataGridOwner).Attributes)
            {
                HashSet<PropertyInfo> currAtts = currType.Value;
                foreach (PropertyInfo currAtt in currAtts)
                {
                    atts.Add(currAtt);
                }
            }

            return new HashSet<PropertyInfo>(atts.OrderBy(att => att.Name));
        }
        #endregion
    }
}
